
import os
import sys
import time


import rpyc
from rpyc.utils import server

import dexen
from dexen.system.common import service
from dexen.system.common.meta import JobMeta
from dexen.system.common.base import MyManager
from dexen.system.common.service import DexenAddr
from dexen.system.node.slave.core import SlaveCore
from dexen.system.node.slave.comm import SlaveComm, InUnit, OutUnit


#===============================================================================
# Globals
#===============================================================================
MyManager.register("SlaveComm", SlaveComm)

#===============================================================================
# Starting
#===============================================================================
def start(_slave_name, _node_name, reg_addr, is_local=False, is_quiet=True):
    global slave_name, node_name, comm
    
    slave_name = _slave_name
    node_name = _node_name
    
    manager = MyManager()
    manager.start()
    
    comm = manager.SlaveComm()
    core = SlaveCore(comm, slave_name)
    core.start()

    SlaveService.ALIASES = [slave_name]
    _logger = service.get_rpyc_logger(slave_name.upper(), is_quiet)
    svr = server.ThreadedServer(SlaveService,
                                protocol_config=service.default_config,
                                auto_register=False,
                                logger=_logger)
    
    assert isinstance(reg_addr, DexenAddr)
    conn = reg_addr.get_conn()
    my_addr = DexenAddr(service.get_my_ip(is_local), svr.port)
    conn.root.register_slave(slave_name, my_addr)
    conn.close()
    
    svr.start()


            
#===============================================================================
# Service Class
#===============================================================================
class SlaveService(dexen.Service):
    def on_connect(self):
        pass
    
    def on_disconnect(self):
        pass

    def setup_schema(self, job_meta):
        #print "I am in slave these are the tasks", tasks
        job_meta = rpyc.classic.obtain(job_meta)
        assert isinstance (job_meta, JobMeta) 
        self.job_id = job_meta.get_id()
        self.job_meta = job_meta
        comm.add_job(job_meta)
        time.sleep(2)

    def execute(self, transact, master_state):
        job_meta = self.job_meta
        assert isinstance(job_meta, JobMeta)
        transact = rpyc.classic.obtain(transact)
        master_state = rpyc.classic.obtain(master_state)
        unit = InUnit(self.job_id, transact, master_state)
        comm.set_in_unit(unit)
        
    def get_output(self):
        """Returns Transaction
        """
        job_meta = self.job_meta
        assert isinstance(job_meta, JobMeta)
        unit = comm.get_out_unit()
        if unit == None: return None
        assert isinstance(unit, OutUnit)
        if unit.job_id == self.job_id:
            return unit.transact
        print "The current job id: ", self.job_id, "old job_id:", unit.job_id 
        return None
            
#===============================================================================
# TESTS
#===============================================================================
def test_suite():
    pass

if __name__ == '__main__':
    test_suite()
    

